package com.netty.controller;

import com.mongodb.BasicDBObject;
import com.netty.common.DateUtil;
import com.netty.common.Result;
import com.netty.mvc.MyRequestParam;
import com.netty.my.MyDiskFileUpload;
import com.netty.utils.*;
import com.netty.mvc.MyController;
import com.netty.mvc.MyRequestMapping;
import com.netty.mvc.MyRequestMethod;
import org.bson.Document;
import org.springframework.util.StringUtils;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static io.netty.buffer.Unpooled.buffer;
import static io.netty.buffer.Unpooled.copiedBuffer;

@MyController
@MyRequestMapping("/netty/file")
public class FileController {


    @MyRequestMapping(value = "/listFileDir", method = MyRequestMethod.POST)
    public Result listFileDir(@MyRequestParam("path") String path) {
        if (StringUtils.isEmpty(path)) {
            path = Constants.FILE_DIRECTORY;
        } else {
            path = Constants.FILE_DIRECTORY + path;
        }
        File[] fs = new File(path).listFiles();
        List<HashMap> collect = Arrays.stream(fs).map(file -> {
            String fileName = file.getName();
            HashMap map = new HashMap();
            map.put("name", fileName);
            map.put("path", file.getPath());
            if (file.isDirectory()) {
                map.put("leaf", false);
            } else {
                return null;
            }
            return map;
        }).filter(map -> {
            return map != null;
        }).collect(Collectors.toList());
        return Result.successResult(collect);
    }

    @MyRequestMapping(value = "/save", method = MyRequestMethod.POST)
    public Result save(@MyRequestParam("directory") String directory,
                       @MyRequestParam("file") File file
    ) throws Exception {
        String fileName = file.getName();
        File newFile = new File(Constants.FILE_DIRECTORY + directory + "/" + fileName);
        file.renameTo(newFile);
        MongoDbUtil mongoDbUtil = new MongoDbUtil();
        //判断是否有重名的文件
        BasicDBObject basicDBObject = new BasicDBObject();
        basicDBObject.put("fileName", fileName);
        basicDBObject.put("directory", directory);
        List<Map<String, Object>> maps = mongoDbUtil.queryByDoc(Constants.FILE_COLLECTION, basicDBObject);
        if (maps.size() > 0) {
            //删掉原来的
            String id = maps.get(0).get("_id").toString();
            mongoDbUtil.deleteById(id, Constants.FILE_COLLECTION);
        }

        //文档信息存入mongodb
        String dataId = UUID.randomUUID().toString();
        HashMap sizeMap = Utils.getSize(newFile.length());
        String unit = sizeMap.get("unit").toString();
        String resultSize = sizeMap.get("resultSize").toString();
        Document document = new Document();
        document.put("_id", dataId);
        document.put("fileName", fileName);
        document.put("fileLength", resultSize + unit);
        document.put("directory", directory);
        document.put("createTime", DateUtil.format(new Date(), DateUtil.DATE_TIME_PATTERN));
        mongoDbUtil.insertDocument(document, Constants.FILE_COLLECTION);
        mongoDbUtil.close();
        return Result.successResult(dataId);
    }


    @MyRequestMapping(value = "cancelUpload", method = MyRequestMethod.GET)
    public Result cancelUpload(@MyRequestParam("uploadId") String uploadId) {
        MongoDbUtil mongoDbUtil = new MongoDbUtil();
        HashMap<String, Object> stringObjectHashMap = mongoDbUtil.queryByID(Constants.UPLOAD_TASK_COLLECTION, uploadId);
        String tmpFileName = stringObjectHashMap.get("tmpFileName").toString();
        File file = new File(Constants.BASE_DIRECTORY + tmpFileName);
        file.delete();
        mongoDbUtil.deleteById(uploadId, Constants.UPLOAD_TASK_COLLECTION);
        mongoDbUtil.close();
        return Result.successResult();
    }


    @MyRequestMapping(value = "cancelDownload", method = MyRequestMethod.GET)
    public Result cancelDownload(@MyRequestParam("downloadId") String downloadId) {
        MongoDbUtil mongoDbUtil = new MongoDbUtil();
        HashMap<String, Object> stringObjectHashMap = mongoDbUtil.queryByID(Constants.DOWNLOAD_TASK_COLLECTION, downloadId);
        Object tmpFileName = stringObjectHashMap.get("tmpFileName");
        if (tmpFileName!=null){
            File file = new File(Constants.BASE_DIRECTORY + tmpFileName);
            file.delete();
        }
        mongoDbUtil.deleteById(downloadId, Constants.DOWNLOAD_TASK_COLLECTION);
        mongoDbUtil.close();
        return Result.successResult();
    }

    @MyRequestMapping(value = "/download", method = MyRequestMethod.POST)
    public Result download(@MyRequestParam("fileId") String fileId,
                           @MyRequestParam("currentFileLength")Long currentFileLength,
                           @MyRequestParam("downloadId") String downloadId,
                           @MyRequestParam("downloadFilePath")String downloadFilePath) throws Exception {
        MongoDbUtil mongoDbUtil = new MongoDbUtil();
        BasicDBObject basicDBObject = new BasicDBObject();
        basicDBObject.put("_id", fileId);
        List<Map<String, Object>> maps = mongoDbUtil.queryByDoc(Constants.FILE_COLLECTION, basicDBObject);
        if (maps.size() > 0) {
            Map<String, Object> map = maps.get(0);
            String directory = map.get("directory").toString();
            String fileName = map.get("fileName").toString();
            String oriFilePath=Constants.FILE_DIRECTORY+directory+"/"+ fileName;
            File file = new File(oriFilePath);
            if (currentFileLength!=0){
                RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
                randomAccessFile.seek(Long.valueOf(currentFileLength));
                String tmpFileName="fup" + UUID.randomUUID().toString();
                File fup = new File(Constants.BASE_DIRECTORY + tmpFileName);
                if (!fup.exists()) {
                    fup.createNewFile();
                }
                FileOutputStream fileOutputStream = new FileOutputStream(fup);
                byte[] bytes = new byte[1024];
                int temp = 0;
                while ((temp = randomAccessFile.read(bytes)) != -1) {
                    fileOutputStream.write(bytes, 0, temp);
                }
                randomAccessFile.close();
                fileOutputStream.close();
                file=fup;

                HashMap downloadTask = mongoDbUtil.queryByID(Constants.DOWNLOAD_TASK_COLLECTION, downloadId);
                if (downloadTask != null) {
                    BasicDBObject updateOldSql = new BasicDBObject("_id", downloadId);
                    BasicDBObject updateNewOneSql = new BasicDBObject("$set",
                            new Document().append("status", "下载中").append("tmpFileName",tmpFileName));
                    mongoDbUtil.updateDocument(updateOldSql, updateNewOneSql, Constants.DOWNLOAD_TASK_COLLECTION);
                }
            }else{
                Document document = new Document();
                document.put("fileName", fileName);
                document.put("fileLength", String.valueOf(file.length()));
                document.put("downloadFilePath", downloadFilePath);
                document.put("fileId", fileId);
                document.put("createTime", DateUtil.format(new Date(), DateUtil.DATE_TIME_PATTERN));
                document.put("status", "下载中");
                document.put("_id", downloadId);
                mongoDbUtil.insertDocument(document, Constants.DOWNLOAD_TASK_COLLECTION);
            }
            mongoDbUtil.close();



            HashMap returnMap = new HashMap();
            returnMap.put("file", file);
            returnMap.put("fileName", fileName);
            returnMap.put("downloadId",downloadId);
            return Result.successResult(returnMap);
        } else {
            mongoDbUtil.close();
            return Result.successResult("该文件不存在");
        }

    }


    @MyRequestMapping(value = "/loadUpload", method = MyRequestMethod.GET)
    public Result loadUpload() {
        MongoDbUtil mongoDbUtil = new MongoDbUtil();
        BasicDBObject basicDBObject = new BasicDBObject();
        basicDBObject.put("status", "已暂停");
        List<Map<String, Object>> maps = mongoDbUtil.queryByDoc(Constants.UPLOAD_TASK_COLLECTION, basicDBObject);
        mongoDbUtil.close();
        maps.forEach(hashMap -> {
            Long fileLength = Long.valueOf(hashMap.get("fileLength").toString());
            Long currentLength = Long.valueOf(hashMap.get("currentLength").toString());
            double l = currentLength.doubleValue() / fileLength.doubleValue();
            BigDecimal bg = new BigDecimal(l);
            double result = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            hashMap.put("progress", result * 100);
        });
        return Result.successResult(maps);
    }



    @MyRequestMapping(value = "/loadDownload", method = MyRequestMethod.GET)
    public Result loadDownload() {
        MongoDbUtil mongoDbUtil = new MongoDbUtil();
        BasicDBObject basicDBObject = new BasicDBObject();
        List<Map<String, Object>> maps = mongoDbUtil.queryByDoc(Constants.DOWNLOAD_TASK_COLLECTION, basicDBObject);
        mongoDbUtil.close();
        maps.forEach(hashMap -> {
            Long fileLength = Long.valueOf(hashMap.get("fileLength").toString());
            String fileName = hashMap.get("fileName").toString();
            String downloadFilePath = hashMap.get("downloadFilePath").toString();
            File file=new File(downloadFilePath+"/"+fileName);
            Long currentLength = file.length();
            double l = currentLength.doubleValue() / fileLength.doubleValue();
            BigDecimal bg = new BigDecimal(l);
            double result = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            hashMap.put("progress", result * 100);
        });
        return Result.successResult(maps);
    }


    @MyRequestMapping(value = "/page", method = MyRequestMethod.POST)
    public Result page(@MyRequestParam("page") int page,
                       @MyRequestParam("pageSize") int pageSize,
                       @MyRequestParam("directory") String directory,
                       @MyRequestParam("fileName") String fileName) {
        MongoDbUtil mongoDbUtil = new MongoDbUtil();
        BasicDBObject basicDBObject = new BasicDBObject();
        directory = directory.replaceAll("\\\\", "/");
        directory = directory.replaceAll(Constants.FILE_DIRECTORY, "");
        basicDBObject.put("directory", directory);
        if (!StringUtils.isEmpty(fileName)) {
            basicDBObject.put("fileName", fileName);
        }

        PageUtils pageUtils = mongoDbUtil.queryPage(Constants.FILE_COLLECTION, basicDBObject,
                page, pageSize, new BasicDBObject("createTime", -1));
        mongoDbUtil.close();
        return Result.successResult(pageUtils);
    }


    @MyRequestMapping("/getTmpFileSize")
    public Result getTmpFileSize(@MyRequestParam("uploadId") String uploadId) {
        MongoDbUtil mongoDbUtil = new MongoDbUtil();
        Map<String, Object> stringObjectMap = mongoDbUtil.queryByID(Constants.UPLOAD_TASK_COLLECTION, uploadId);
        if(stringObjectMap==null){
            return Result.errorResult(800,"文件还没开始上传");
        }
        String tmpFileName = stringObjectMap.get("tmpFileName").toString();
        String fileName = stringObjectMap.get("fileName").toString();
        File file = new File(MyDiskFileUpload.baseDirectory + tmpFileName);
        mongoDbUtil.close();
        if (file.exists()) {
            HashMap hashMap = new HashMap();
            hashMap.put("length", file.length());
            hashMap.put("fileName", fileName);
            return Result.successResult(hashMap);
        }
        return Result.errorResult("该文件已经上传完了");
    }


    @MyRequestMapping(value = "/makeDir", method = MyRequestMethod.POST)
    public Result makeDir(@MyRequestParam("dirName") String dirName, @MyRequestParam("parentPath") String parentPath) {
        String path = null;
        if (StringUtils.isEmpty(parentPath)) {
            parentPath = Constants.FILE_DIRECTORY;
            path = parentPath + dirName;
        } else {
            path = parentPath + "/" + dirName;
        }
        File file = new File(path);
        boolean mkdir = file.mkdir();
        if (mkdir) {
            return Result.successResult();
        }
        return Result.errorResult(dirName + "目录已存在");
    }


}
